package com.suhuamo.stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;

public class SimpleStreamBuilder<T> {
    private List<T> elements;
    private List<StreamOperation<T, ?>> operations = new ArrayList<>();

    public SimpleStreamBuilder(List<T> elements) {
        this.elements = new ArrayList<>(elements);
    }

    public <R> SimpleStreamBuilder<R> filter(Predicate<? super T> predicate) {
        // 需要对用户传入的方法再次进行封装，因为用户的方法是对一个元素操作，我们需要将这个操作作用到所有元素上
        operations.add(new FilterOperation<>(predicate));
        return (SimpleStreamBuilder<R>) this;
    }

    public <R> SimpleStreamBuilder<R> map(Function<? super T, ? extends R> function) {
        // 需要对用户传入的方法再次进行封装，因为用户的方法是对一个元素操作，我们需要将这个操作作用到所有元素上
        operations.add(new MapOperation<>(function));
        return (SimpleStreamBuilder<R>) this;
    }

    @SuppressWarnings("unchecked")
    public List<T> collect() {
        // 创建新的集合对象
        List<T> result = new ArrayList<>(elements);
        // 执行用户给出的每个操作
        for (StreamOperation<T, ?> operation : operations) {
            result = (List<T>) operation.apply(result);
        }
        return result;
    }

    // 操作接口类
    private abstract static class StreamOperation<T, R> {
        abstract List<R> apply(List<T> input);
    }

    private static class FilterOperation<T> extends StreamOperation<T, T> {
        private final Predicate<? super T> predicate;

        FilterOperation(Predicate<? super T> predicate) {
            this.predicate = predicate;
        }

        @Override
        List<T> apply(List<T> input) {
            List<T> result = new ArrayList<>();
            for (T element : input) {
                if (predicate.test(element)) {
                    result.add(element);
                }
            }
            return result;
        }
    }

    private static class MapOperation<T, R> extends StreamOperation<T, R> {
        private final Function<? super T, ? extends R> function;

        MapOperation(Function<? super T, ? extends R> function) {
            this.function = function;
        }

        @Override
        List<R> apply(List<T> input) {
            List<R> result = new ArrayList<>();
            for (T element : input) {
                result.add(function.apply(element));
            }
            return result;
        }
    }

    // For demonstration purposes, a main method to show usage
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        List<Integer> result = new SimpleStreamBuilder<>(numbers)
                .<Integer>filter(n -> n % 2 == 0)
                .<Integer>map(n -> n * 2)
                .collect();

        System.out.println(result);
    }
}